/**
 * Prometheus Metrics Collection
 * EndoSight-UC 医疗AI系统
 *
 * 提供全面的系统监控指标收集
 */

import winston from 'winston';

// 配置日志记录器
const logger = winston.createLogger({
  level: 'info',
  format: winston.format.combine(
    winston.format.timestamp(),
    winston.format.json()
  ),
  transports: [
    new winston.transports.Console({
      format: winston.format.simple()
    })
  ]
});

// Prometheus格式指标存储
const metrics = new Map();

// 指标类型枚举
export const MetricTypes = {
  COUNTER: 'counter',
  GAUGE: 'gauge',
  HISTOGRAM: 'histogram',
  SUMMARY: 'summary'
};

// 创建指标的工厂函数
export const createMetric = (name, type, help, labels = []) => {
  const key = `${name}_${type}`;

  if (metrics.has(key)) {
    return metrics.get(key);
  }

  const metric = {
    name,
    type,
    help,
    labels,
    values: new Map(),
    createdAt: new Date().toISOString()
  };

  metrics.set(key, metric);
  logger.info(`创建指标: ${name} (${type})`);

  return metric;
};

// Counter 指标（只增不减）
export const incrementCounter = (name, labels = {}, value = 1) => {
  const metric = createMetric(name, MetricTypes.COUNTER, `${name} counter`);
  const labelKey = JSON.stringify(labels);

  const currentValue = metric.values.get(labelKey) || 0;
  metric.values.set(labelKey, currentValue + value);

  logger.debug(`Counter ${name} 增加到: ${currentValue + value}`, { labels });
};

// Gauge 指标（可增可减）
export const setGauge = (name, value, labels = {}) => {
  const metric = createMetric(name, MetricTypes.GAUGE, `${name} gauge`);
  const labelKey = JSON.stringify(labels);

  metric.values.set(labelKey, value);

  logger.debug(`Gauge ${name} 设置为: ${value}`, { labels });
};

// Histogram 指标（分布统计）
export const observeHistogram = (name, value, labels = {}, buckets = [0.1, 0.5, 1, 2, 5, 10, 30, 60, 120]) => {
  const metric = createMetric(name, MetricTypes.HISTOGRAM, `${name} histogram`, ['le']);
  const labelKey = JSON.stringify(labels);

  if (!metric.values.has(labelKey)) {
    metric.values.set(labelKey, {
      count: 0,
      sum: 0,
      buckets: buckets.map(bucket => ({ le: bucket, count: 0 }))
    });
  }

  const histogram = metric.values.get(labelKey);
  histogram.count++;
  histogram.sum += value;

  // 更新桶计数
  for (const bucket of buckets) {
    if (value <= bucket) {
      const bucketItem = histogram.buckets.find(b => b.le === bucket);
      if (bucketItem) {
        bucketItem.count++;
      }
    }
  }

  logger.debug(`Histogram ${name} 观察: ${value}`, { labels });
};

// 业务指标定义
export const BusinessMetrics = {
  // HTTP请求指标
  HTTP_REQUESTS_TOTAL: 'http_requests_total',
  HTTP_REQUEST_DURATION_SECONDS: 'http_request_duration_seconds',
  HTTP_REQUESTS_ERRORS_TOTAL: 'http_requests_errors_total',

  // AI推理指标
  AI_INFERENCE_TOTAL: 'ai_inference_total',
  AI_INFERENCE_DURATION_SECONDS: 'ai_inference_duration_seconds',
  AI_INFERENCE_ERRORS_TOTAL: 'ai_inference_errors_total',
  AI_INFERENCE_QUEUE_SIZE: 'ai_inference_queue_size',

  // 数据库指标
  DB_CONNECTIONS_ACTIVE: 'db_connections_active',
  DB_QUERY_DURATION_SECONDS: 'db_query_duration_seconds',
  DB_QUERIES_TOTAL: 'db_queries_total',
  DB_ERRORS_TOTAL: 'db_errors_total',

  // 文件上传指标
  FILE_UPLOADS_TOTAL: 'file_uploads_total',
  FILE_UPLOADS_BYTES_TOTAL: 'file_uploads_bytes_total',
  FILE_UPLOADS_DURATION_SECONDS: 'file_uploads_duration_seconds',
  FILE_VALIDATION_ERRORS_TOTAL: 'file_validation_errors_total',

  // 系统资源指标
  SYSTEM_MEMORY_USAGE_BYTES: 'system_memory_usage_bytes',
  SYSTEM_CPU_USAGE_PERCENT: 'system_cpu_usage_percent',
  SYSTEM_DISK_USAGE_BYTES: 'system_disk_usage_bytes',

  // 业务特定指标
  SCORING_TASKS_TOTAL: 'scoring_tasks_total',
  SCORING_TASKS_COMPLETED: 'scoring_tasks_completed',
  SCORING_TASKS_ERRORS: 'scoring_tasks_errors',
  PATIENT_RECORDS_TOTAL: 'patient_records_total',
  DOCTOR_SESSIONS_ACTIVE: 'doctor_sessions_active'
};

// 便捷的业务指标操作函数
export const trackHttpRequest = (method, route, statusCode, duration) => {
  const labels = { method, route, status_code: statusCode.toString() };

  incrementCounter(BusinessMetrics.HTTP_REQUESTS_TOTAL, labels);
  observeHistogram(BusinessMetrics.HTTP_REQUEST_DURATION_SECONDS, duration, labels);

  if (statusCode >= 400) {
    incrementCounter(BusinessMetrics.HTTP_REQUESTS_ERRORS_TOTAL, labels);
  }
};

export const trackAIInference = (duration, success = true, errorType = null) => {
  const labels = success ? { status: 'success' } : { status: 'error', error_type: errorType || 'unknown' };

  incrementCounter(BusinessMetrics.AI_INFERENCE_TOTAL, labels);
  observeHistogram(BusinessMetrics.AI_INFERENCE_DURATION_SECONDS, duration, labels);

  if (!success) {
    incrementCounter(BusinessMetrics.AI_INFERENCE_ERRORS_TOTAL, labels);
  }
};

export const trackDatabaseQuery = (operation, duration, success = true) => {
  const labels = { operation, status: success ? 'success' : 'error' };

  incrementCounter(BusinessMetrics.DB_QUERIES_TOTAL, labels);
  observeHistogram(BusinessMetrics.DB_QUERY_DURATION_SECONDS, duration, labels);

  if (!success) {
    incrementCounter(BusinessMetrics.DB_ERRORS_TOTAL, labels);
  }
};

export const trackFileUpload = (size, duration, success = true, errorType = null) => {
  const labels = success ? { status: 'success' } : { status: 'error', error_type: errorType || 'unknown' };

  incrementCounter(BusinessMetrics.FILE_UPLOADS_TOTAL, labels);
  observeHistogram(BusinessMetrics.FILE_UPLOADS_DURATION_SECONDS, duration, labels);

  if (success) {
    // 创建临时指标来跟踪文件大小
    createMetric('file_upload_size_bytes', MetricTypes.HISTOGRAM, 'File upload size in bytes', ['le']);
    observeHistogram('file_upload_size_bytes', size, labels);
  }
};

export const trackScoringTask = (status, duration = null) => {
  incrementCounter(BusinessMetrics.SCORING_TASKS_TOTAL, { status });

  if (status === 'completed') {
    incrementCounter(BusinessMetrics.SCORING_TASKS_COMPLETED);
    if (duration) {
      observeHistogram('scoring_task_duration_seconds', duration, { status });
    }
  } else if (status === 'error') {
    incrementCounter(BusinessMetrics.SCORING_TASKS_ERRORS);
  }
};

// 系统指标收集
export const collectSystemMetrics = async () => {
  try {
    const process = await import('process');
    const fs = await import('fs');

    // 内存使用情况
    const memUsage = process.memoryUsage();
    setGauge(BusinessMetrics.SYSTEM_MEMORY_USAGE_BYTES, memUsage.rss);
    setGauge('nodejs_memory_heap_used_bytes', memUsage.heapUsed);
    setGauge('nodejs_memory_heap_total_bytes', memUsage.heapTotal);
    setGauge('nodejs_memory_external_bytes', memUsage.external);

    // CPU使用情况（简化版）
    const cpuUsage = process.cpuUsage();
    setGauge('nodejs_cpu_user_seconds_total', cpuUsage.user / 1000000);
    setGauge('nodejs_cpu_system_seconds_total', cpuUsage.system / 1000000);

    // 事件循环延迟
    setGauge('nodejs_eventloop_lag_seconds', 0); // 简化实现

    // 活跃句柄数
    setGauge('nodejs_active_handles_total', process._getActiveHandles().length);
    setGauge('nodejs_active_requests_total', process._getActiveRequests().length);

    // 磁盘使用情况
    try {
      const stats = fs.statSync('.');
      // 这里可以添加更详细的磁盘使用统计
      setGauge('process_uptime_seconds', process.uptime());
    } catch (error) {
      logger.debug('无法获取磁盘统计信息:', error.message);
    }

  } catch (error) {
    logger.error('收集系统指标失败:', error);
  }
};

// 生成Prometheus格式的指标输出
export const generatePrometheusMetrics = () => {
  let output = '';

  // 添加时间戳注释
  output += `# EndoSight-UC Medical AI System Metrics\n`;
  output += `# Generated at: ${new Date().toISOString()}\n\n`;

  for (const [key, metric] of metrics) {
    output += `# HELP ${metric.name} ${metric.help}\n`;
    output += `# TYPE ${metric.name} ${metric.type}\n`;

    for (const [labelKey, value] of metric.values) {
      const labels = JSON.parse(labelKey);

      if (metric.type === MetricTypes.COUNTER || metric.type === MetricTypes.GAUGE) {
        const labelStr = Object.keys(labels).length > 0
          ? `{${Object.entries(labels).map(([k, v]) => `${k}="${v}"`).join(',')}}`
          : '';
        output += `${metric.name}${labelStr} ${value}\n`;
      } else if (metric.type === MetricTypes.HISTOGRAM) {
        const labelStr = Object.keys(labels).length > 0
          ? `{${Object.entries(labels).map(([k, v]) => `${k}="${v}"`).join(',')}}`
          : '';

        // 添加桶计数
        for (const bucket of value.buckets) {
          const bucketLabels = { ...labels, le: bucket.le.toString() };
          const bucketLabelStr = Object.keys(bucketLabels).length > 0
            ? `{${Object.entries(bucketLabels).map(([k, v]) => `${k}="${v}"`).join(',')}}`
            : '';
          output += `${metric.name}_bucket${bucketLabelStr} ${bucket.count}\n`;
        }

        // 添加总数和总和
        output += `${metric.name}_count${labelStr} ${value.count}\n`;
        output += `${metric.name}_sum${labelStr} ${value.sum}\n`;
      }
    }

    output += '\n';
  }

  return output;
};

// 重置所有指标（主要用于测试）
export const resetAllMetrics = () => {
  metrics.clear();
  logger.info('所有指标已重置');
};

// 获取指标摘要信息
export const getMetricsSummary = () => {
  const summary = {
    totalMetrics: metrics.size,
    metricTypes: {},
    totalValues: 0,
    lastUpdated: new Date().toISOString()
  };

  for (const [key, metric] of metrics) {
    summary.metricTypes[metric.type] = (summary.metricTypes[metric.type] || 0) + 1;
    summary.totalValues += metric.values.size;
  }

  return summary;
};

// 初始化业务指标
export const initializeBusinessMetrics = () => {
  // 预创建所有业务指标
  Object.values(BusinessMetrics).forEach(metricName => {
    createMetric(metricName, MetricTypes.COUNTER, `${metricName} metric`);
  });

  logger.info('业务指标初始化完成');
};

// 定期收集系统指标的定时器
let systemMetricsTimer = null;

export const startSystemMetricsCollection = (intervalMs = 30000) => {
  if (systemMetricsTimer) {
    clearInterval(systemMetricsTimer);
  }

  systemMetricsTimer = setInterval(collectSystemMetrics, intervalMs);
  logger.info(`系统指标收集已启动，间隔: ${intervalMs}ms`);

  // 立即执行一次
  collectSystemMetrics();
};

export const stopSystemMetricsCollection = () => {
  if (systemMetricsTimer) {
    clearInterval(systemMetricsTimer);
    systemMetricsTimer = null;
    logger.info('系统指标收集已停止');
  }
};

export default {
  createMetric,
  incrementCounter,
  setGauge,
  observeHistogram,
  trackHttpRequest,
  trackAIInference,
  trackDatabaseQuery,
  trackFileUpload,
  trackScoringTask,
  collectSystemMetrics,
  generatePrometheusMetrics,
  resetAllMetrics,
  getMetricsSummary,
  initializeBusinessMetrics,
  startSystemMetricsCollection,
  stopSystemMetricsCollection,
  BusinessMetrics,
  MetricTypes
};